var o = Object.defineProperty;
var g = (c, t, e) =>
  t in c
    ? o(c, t, { enumerable: !0, configurable: !0, writable: !0, value: e })
    : (c[t] = e);
var r = (c, t, e) => (g(c, typeof t != 'symbol' ? t + '' : t, e), e);
import { isNode as h } from '../nodes/identity.js';
import { visit as m } from '../visit.js';
const d = {
    '!': '%21',
    ',': '%2C',
    '[': '%5B',
    ']': '%5D',
    '{': '%7B',
    '}': '%7D',
  },
  p = c => c.replace(/[!,[\]{}]/g, t => d[t]),
  n = class n {
    constructor(t, e) {
      r(this, 'yaml');
      r(this, 'tags');
      /**
       * The directives-end/doc-start marker `---`. If `null`, a marker may still be
       * included in the document's stringified representation.
       */
      r(this, 'docStart', null);
      /** The doc-end marker `...`.  */
      r(this, 'docEnd', !1);
      /**
       * Used when parsing YAML 1.1, where:
       * > If the document specifies no directives, it is parsed using the same
       * > settings as the previous document. If the document does specify any
       * > directives, all directives of previous documents, if any, are ignored.
       */
      r(this, 'atNextDocument');
      (this.yaml = Object.assign({}, n.defaultYaml, t)),
        (this.tags = Object.assign({}, n.defaultTags, e));
    }
    clone() {
      const t = new n(this.yaml, this.tags);
      return (t.docStart = this.docStart), t;
    }
    /**
     * During parsing, get a Directives instance for the current document and
     * update the stream state according to the current version's spec.
     */
    atDocument() {
      const t = new n(this.yaml, this.tags);
      switch (this.yaml.version) {
        case '1.1':
          this.atNextDocument = !0;
          break;
        case '1.2':
          (this.atNextDocument = !1),
            (this.yaml = {
              explicit: n.defaultYaml.explicit,
              version: '1.2',
            }),
            (this.tags = Object.assign({}, n.defaultTags));
          break;
      }
      return t;
    }
    /**
     * @param onError - May be called even if the action was successful
     * @returns `true` on success
     */
    add(t, e) {
      this.atNextDocument &&
        ((this.yaml = { explicit: n.defaultYaml.explicit, version: '1.1' }),
        (this.tags = Object.assign({}, n.defaultTags)),
        (this.atNextDocument = !1));
      const a = t.trim().split(/[ \t]+/),
        l = a.shift();
      switch (l) {
        case '%TAG': {
          if (
            a.length !== 2 &&
            (e(0, '%TAG directive should contain exactly two parts'),
            a.length < 2)
          )
            return !1;
          const [s, i] = a;
          return (this.tags[s] = i), !0;
        }
        case '%YAML': {
          if (((this.yaml.explicit = !0), a.length !== 1))
            return e(0, '%YAML directive should contain exactly one part'), !1;
          const [s] = a;
          if (s === '1.1' || s === '1.2') return (this.yaml.version = s), !0;
          {
            const i = /^\d+\.\d+$/.test(s);
            return e(6, `Unsupported YAML version ${s}`, i), !1;
          }
        }
        default:
          return e(0, `Unknown directive ${l}`, !0), !1;
      }
    }
    /**
     * Resolves a tag, matching handles to those defined in %TAG directives.
     *
     * @returns Resolved tag, which may also be the non-specific tag `'!'` or a
     *   `'!local'` tag, or `null` if unresolvable.
     */
    tagName(t, e) {
      if (t === '!') return '!';
      if (t[0] !== '!') return e(`Not a valid tag: ${t}`), null;
      if (t[1] === '<') {
        const i = t.slice(2, -1);
        return i === '!' || i === '!!'
          ? (e(`Verbatim tags aren't resolved, so ${t} is invalid.`), null)
          : (t[t.length - 1] !== '>' && e('Verbatim tags must end with a >'),
            i);
      }
      const [, a, l] = t.match(/^(.*!)([^!]*)$/);
      l || e(`The ${t} tag has no suffix`);
      const s = this.tags[a];
      if (s)
        try {
          return s + decodeURIComponent(l);
        } catch (i) {
          return e(String(i)), null;
        }
      return a === '!' ? t : (e(`Could not resolve tag: ${t}`), null);
    }
    /**
     * Given a fully resolved tag, returns its printable string form,
     * taking into account current tag prefixes and defaults.
     */
    tagString(t) {
      for (const [e, a] of Object.entries(this.tags))
        if (t.startsWith(a)) return e + p(t.substring(a.length));
      return t[0] === '!' ? t : `!<${t}>`;
    }
    toString(t) {
      const e = this.yaml.explicit
          ? [`%YAML ${this.yaml.version || '1.2'}`]
          : [],
        a = Object.entries(this.tags);
      let l;
      if (t && a.length > 0 && h(t.contents)) {
        const s = {};
        m(t.contents, (i, f) => {
          h(f) && f.tag && (s[f.tag] = !0);
        }),
          (l = Object.keys(s));
      } else l = [];
      for (const [s, i] of a)
        (s === '!!' && i === 'tag:yaml.org,2002:') ||
          ((!t || l.some(f => f.startsWith(i))) && e.push(`%TAG ${s} ${i}`));
      return e.join(`
`);
    }
  };
r(n, 'defaultYaml', { explicit: !1, version: '1.2' }),
  r(n, 'defaultTags', { '!!': 'tag:yaml.org,2002:' });
let u = n;
export { u as Directives };
